package idv.cjcat.pyronova.nodes {
	import flash.utils.Dictionary;
	import idv.cjcat.pyronova.render.RenderVisitor;
	
	public class Group extends Node implements IGroup {
		
		/** @private */
		protected var _fistEmptyIndex:int = 0;
		/** @private */
		protected var _children:Vector.<Node> = new Vector.<Node>();
		/** @private */
		protected var _childrenIndicies:Dictionary = new Dictionary();
		
		public function get numChildren():int { return _fistEmptyIndex };
		
		public function Group(...children) {
			for (var i:int = 0, len:int = children.length; i < len; ++i) {
				add(children[i]);
			}
		}
		
		
		//children management
		//------------------------------------------------------------------------------------------------
		
		public function add(child:Node):void {
			if (_childrenIndicies[child] !== undefined) return;
			
			//remove from original parent
			if (child._parent) child._parent.remove(child);
			
			//expand vector if full
			_children[_fistEmptyIndex] = child;
			_childrenIndicies[child] = _fistEmptyIndex;
			if (++_fistEmptyIndex == _children.length) _children.length <<= 1;
		}
		
		public function remove(child:Node):void {
			if (_childrenIndicies[child] !== undefined) {
				
				//null parent
				child._parent = null;
				
				//remove from vector
				var index:int = _childrenIndicies[child];
				_children[index] = _children[--_fistEmptyIndex];
				_children[_fistEmptyIndex] = null;
				delete _childrenIndicies[child];
			}
		}
		
		public function clear():void {
			var child:Node;
			for (var i:int = 0; i < _fistEmptyIndex; ++i) {
				child = _children[i];
				
				//null parent
				child._parent = null;
				
				//clear record
				delete _childrenIndicies[child];
				
				//empty vector element
				_children[i] = null;
			}
			
			_fistEmptyIndex = 0;
		}
		
		//------------------------------------------------------------------------------------------------
		//end of children management
		
		
		//children visiting
		//------------------------------------------------------------------------------------------------
		
		private var child:Node;
		override public function render(visitor:RenderVisitor):void {
			visitor.pushMatrix(matrix());
			
			for (var i:int = 0; i < _fistEmptyIndex; ++i) {
				child = _children[i];
				
				//update index dictionary
				_childrenIndicies[child] = i;
				
				//visit child
				child.render(visitor);
			}
			
			visitor.popMatrix();
		}
	}
}